package com.xdl.flytest.util.runner;


import com.fasterxml.jackson.databind.ObjectMapper;
import com.xdl.flytest.util.docker.DockerEnvironmentConfig;
import com.xdl.flytest.util.docker.DockerManager;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;

import java.io.*;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.UUID;

/**
 * @Auther: 80736
 * @Date: 2019/2/4 15:35
 * @Description: docker容器管理
 */

@Component
@Deprecated
public class DockerContainerManager {

    private String dockerContainerName;

    public DockerContainerManager() {
        SimpleDateFormat sf = new SimpleDateFormat("yyyy-MM-dd-HH-mm-ss");
        String date = sf.format(new Date());
        this.dockerContainerName = String.format("runner_container_%s", date.replace("-", "_"));
    }

    public DockerContainerManager(String dockerContainerName) {
        this.dockerContainerName = dockerContainerName;
    }

    public String getDockerContainerName() {
        return dockerContainerName;
    }

    public void setDockerContainerName(String dockerContainerName) {
        this.dockerContainerName = dockerContainerName;
    }


    private Logger logger = LoggerFactory.getLogger(this.getClass());


    /**
     * 创建容器
     *
     * @param imageName 镜像名称
     * @return 容器id
     */
    public String createContainer(String imageName) throws InterruptedException {
        String cmd = String.format("docker run -itd --name %s -p 9988:9988 %s /bin/bash", dockerContainerName, imageName);
        execCmdResult(cmd);
        Thread.sleep(500);
        return getContainerIdByName();
    }


    /**
     * 根据容器名称获取容器id
     *
     * @return 容器id
     */
    public String getContainerIdByName() {
        // 获取所有容器
        String cmd = "docker container ps -a";
        //  获取容器id
        List<String[]> dockerContainerList = execCmdResult(cmd);
        return searchContainerIdInResultList(dockerContainerList);
    }


    /**
     * 根据容器名称获取正在运行中的容器id
     *
     * @return 容器id
     */
    public String getRunningContainerByName() {
        // 获取当前运行的容器
        String cmd = "docker container ps";
        //  获取容器id
        List<String[]> dockerContainerList = execCmdResult(cmd);
        return searchContainerIdInResultList(dockerContainerList);
    }

    /**
     * 根据容器名称从命令行返回结果中提取容器id
     *
     * @param list 命令返回结果
     * @return 容器id
     */
    public String searchContainerIdInResultList(List<String[]> list) {
        //  获取容器id
        for (String[] container : list) {
            if (container[container.length - 1].equals(dockerContainerName)) {
                return container[0];
            }
        }
        return null;
    }

    /**
     * 根据容器名称删除容器
     *
     * @return
     */
    public boolean removeContainer() throws IOException, InterruptedException {
        // 1.检查容器状态，先stop正在运行中的容器
        String runningContainerId = getRunningContainerByName();
        if (runningContainerId != null) {
            logger.debug(String.format("容器：%s正在运行，准备停止", runningContainerId));
            execCmdResult(String.format("docker container stop %s", runningContainerId));
            Thread.sleep(1000);
            logger.debug(String.format("容器%s已停止", runningContainerId));
        }

        // 2.已经停止的容器，直接删除
        String stopedContainnerId = getContainerIdByName();
        if (stopedContainnerId != null) {
            logger.debug("发现已停止的容器id:" + stopedContainnerId + "，开始删除！");
            execCmdResult(String.format("docker container rm %s", stopedContainnerId));
            Thread.sleep(1000);
            logger.debug(String.format("删除容器：%s成功", stopedContainnerId));
        } else {
            throw new RuntimeException(String.format("当前id为：%s的容器不存在", stopedContainnerId));
        }
        return true;
    }

    /**
     * 获得cmd命令执行后的结果
     *
     * @param cmd
     * @return
     */
    public List<String[]> execCmdResult(String cmd) {

        logger.info("【CMD】" + cmd);
        List<String[]> list = new ArrayList<>();
        Runtime rt = Runtime.getRuntime(); // 运行时系统获取
        try {
            Process proc = rt.exec(cmd);// 执行命令
            InputStream stderr = proc.getInputStream();//执行结果 得到进程的标准输出信息流
            InputStreamReader isr = new InputStreamReader(stderr, "GBK");//将字节流转化成字符流
            BufferedReader br = new BufferedReader(isr);//将字符流以缓存的形式一行一行输出
            String line = null;
            while ((line = br.readLine()) != null) {
                if (!StringUtils.isEmpty(line) && !line.contains("fail") && !line.contains("error")) {
                    String newLine = line.replaceAll(" {2,}", " ");
                    String[] strLine = newLine.split(" ");
                    list.add(strLine);
                }
            }
            br.close();
            isr.close();
            stderr.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return list;
    }


    /**
     * 获取名称为flyhttprunner的image id
     *
     * @return 镜像id
     */
    public String getImageId() {
        String imageId = null;
        List<String[]> dockerImages = execCmdResult("docker images");
        for (String[] dockerImage : dockerImages) {
            if (dockerImage[0].equals(DockerEnvironmentConfig.IMAGE_NAME)) {
                imageId = dockerImage[2];
            }
        }
        return imageId;
    }

    /**
     * 本地创建json文件
     *
     * @param data 写入数据
     * @return 文件绝对路径
     * @throws IOException
     */
    public String createJsonFile(String data) throws IOException {
        SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd-HH-mm-ss"); //设置日期格式
        String nowTime = df.format(new Date());
        String uuid = getUUID();
        String fileName = String.format("TestCase-%s-%s.json", uuid.substring(uuid.length() - 6), nowTime);
        File jsonFile = new File(DockerEnvironmentConfig.JSON_FILE_PATH, fileName);
        ObjectMapper mapper = new ObjectMapper();
        Object obj = mapper.readValue(data, Object.class);
        mapper.writerWithDefaultPrettyPrinter().writeValue(jsonFile, obj);
        logger.debug(String.format("create json file in %s", jsonFile.getAbsolutePath()));
        return jsonFile.getAbsolutePath();

    }

    /**
     * 创建httprunner demo
     *
     * @param containerId 容器id
     * @param projectPath 容器内创建demo的目录
     */
    public void createTestProject(String containerId, String projectPath) {
        execCmdResult(String.format("docker exec %s hrun --startproject %s", containerId, projectPath));
        logger.debug("create httprunner demo project");
    }

    /**
     * 从本地复制json文件到容器
     *
     * @param from        本地文件地址
     * @param to          docker文件夹地址
     * @param containerId 容器id
     */
    public void copyLocalFile(String containerId, String from, String to) {
        // 4.复制json文件到容器，在容器内指定文件夹创建*.json测试文件.
        execCmdResult(String.format("docker cp %s %s:%s", from, containerId, to));
        logger.debug("cp json file to container dir");
    }

    /**
     * 从docker复制文件到本地
     *
     * @param from        docker文件地址
     * @param to          本地地址
     * @param containerId 容器id
     */
    public void copyDockerFile(String containerId, String from, String to) {
        // 4.复制json文件到容器，在容器内指定文件夹创建*.json测试文件.
        execCmdResult(String.format("docker cp  %s:%s %s", containerId, from, to));
        logger.debug(String.format("in container %s from %s cp to local %s", containerId, from, to));
    }


    /**
     * 获得一个UUID
     *
     * @return String UUID
     */
    public static String getUUID() {
        String uuid = UUID.randomUUID().toString();
        //去掉“-”符号
        return uuid.replaceAll("-", "");
    }


}
